class Vote < ActiveRecord::Base
  belongs_to :tag
  belongs_to :image_fact
  validates_uniqueness_of :image_fact_id, :scope => :tag_id
  
  # cast a balanced vote: one where one object wins and the other loses.
  def self.balanced(winner, loser, tagname, magnitude=100)
    self.place(winner, tagname, magnitude, 0)
    self.place(loser,  tagname, 0, magnitude)
  end

  # cast an unbalanced vote: where one object get P positive and N negative votes all in one go
  def self.place(image_fact, tagname, p, n) # positive and negative .. increase votes by given offset
    self.mangle(image_fact, tagname) { |v| v.plus_votes += p; v.minus_votes += n; v }
  end
  
  # Set the vote totals for one object unilaterally by positive votes and total denominator
  def self.set(image_fact, tagname, p, d) # positive and denominator .. REPLACE (or initialize) vote values with given values
    self.mangle(image_fact, tagname) { |v| v.plus_votes = p; v.minus_votes = d-p; v }
  end
  
  # Takes same perams as "fetch", also a block.
  # fetches the requested vote, runs the block on the requested vote (setting vote values or whatever you want)
  # and then calculates perc and saves the vote.
  def self.mangle(image_fact, tagname, &block)
    vote  = Vote.find_or_initialize_by_image_fact_id_and_tag_id(:image_fact_id => image_fact.id, :tag_id => Tag.find_by_tagname(tagname).id)
    vote = self.fetch(image_fact, tagname, &block)
    vote.perc = (1.0 * vote.plus_votes / (vote.plus_votes+vote.minus_votes) * 1e6).floor
    vote.save!
  end

  def self.text1(tagval)
    tag = Tag.invoke tagval
    Vote.find_all_by_tag_id(tag.id, :order => "perc desc").each { |v| puts "%10d %8.4f%%" % [v.image_fact_id, v.perc/1e4] }
    nil
  end
  
  # fetch a vote based on a given image_fact and a name of a tag.
  # no block, return vote.
  # Block? Run block, return that.
  def self.fetch(image_fact, tagname)
    vote = Vote.find_or_initialize_by_image_fact_id_and_tag_id(:image_fact_id => image_fact.id, :tag_id => Tag.find_by_tagname(tagname).id)
    return block_given? ? yield(vote) : vote
  end
end
